﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

using sfsocket.corelib.message;


namespace sfsocket.corelib.connection.client
{
    public class ChatClientIdleThread
    {
        private ChatClientConnection m_Connection;
        private Thread m_Thread;
        private bool m_IsStarted = false;

        public bool IsStarted
        {
            get { return m_IsStarted; }
            set { m_IsStarted = value; }
        }

        public ChatClientIdleThread(ChatClientConnection con)
        {
            m_Connection = con;
        }

        public void Start()
        {
            if (!m_IsStarted)
            {
                DateTime now = DateTime.Now;
                m_Connection.LastPingSent = now;
                m_Connection.LastPongReceived = now;

                m_Thread = new Thread(new ThreadStart(_Worker));
                m_Thread.Name = "Idle Thread";
                m_Thread.IsBackground = true;
                m_Thread.Start();
                m_IsStarted = true;
            }
        }

        public void Stop()
        {
            if (m_IsStarted)
            {
                m_Thread.Abort();
                m_IsStarted = false;
                try
                {
                    m_Connection.Disconnect();
                }
                catch (Exception ex)
                {
                    TraceMsg(ex.Message);
                }
            }
        }

        private void _Worker()
        {
            TraceMsg("Entering Idle Worker thread");
            try
            {
                while (m_Connection.IsConnected)
                {
                    DateTime now = DateTime.Now;
                    int last_ping_sent = (now - m_Connection.LastPingSent).Seconds;
                    int last_pont_recv = (now - m_Connection.LastPongReceived).Seconds;

                    // if last ping is not timeout and don't receive pong, sent ping again
                    if (last_ping_sent < m_Connection.PingTimeout)
                    {
                        if (last_pont_recv > m_Connection.PingInterval)
                        {
                            // send ping message
                            BaseMessage pingMsg = new PingMessage();
                            TraceMsg("Send Ping Msg");
                            m_Connection.SendMsg(pingMsg);

                            m_Connection.LastPingSent = now;
                            m_Connection.LastPongReceived = now;
                        }
                        else
                        {
                            // connection pong recv, do nothing
                        }

                    }
                    else 
                    {
                        // ping time out 
                        TraceMsg("ping time out, connection lost");

                    }
                    // sleep 60 seconds 
                    Thread.Sleep(m_Connection.IdleWorkerInterval);
                }
            }
            catch (ThreadAbortException ex)
            {
                TraceMsg(ex.Message);
                Thread.ResetAbort();
            }
            catch (System.Exception e)
            {
                TraceMsg(e.Message);
                throw e;
            }
            finally
            {
                Stop();
                TraceMsg("stoping idle thread");
            }
        }

        private void TraceMsg(string msg)
        {
            Console.WriteLine("[{0,3}] - {1} : {2}",
                    Thread.CurrentThread.ManagedThreadId,
                    DateTime.Now.ToString("HH:mm:ss.ffff"), msg);
        }
    }


    public class IdleThreadTest
    {
        public static void TestIdleThread()
        {

        }

    }

}
